`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//	Author: 	Nick
// 
// Create Date:    16:14:37 01/12/2011 
// Design Name: 	 
// Module Name:    datapath 
// Project Name:   Project1
// Target Devices: 
// Tool versions: 
// Description: top level interface for datapath
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module datapath
(
	// All of these signals originate from the control section of the processor
	// Controls the operation of the processor, determining if it should be stalled, reset or running
	input [1:0] run_stall_reset_sel_in,
	// Tells the register file that we want to write this cycle
	input regfile_write_en_in,
	// Tells the dmem wrapper if we're going to read or write this cycle
	input dmem_read_write_req_in,
	// Selects from where the register file should derive its write input
	input [1:0] reg_sel_in,
	// Signals DRAM that it should write at the end of this cycle
	input dmem_write_en_in,
	// Tells the ALU which operation (ADD, SUB, MULT) it should perform this cycle
	input [1:0] alu_op_code_in,

	// This signal allows the control section of the processor access to the current instruction
	output [3:0] inst_out,
	
	// Global clock
	input clk,
	// Global reset
	input reset,
	
	// All of these signals come from or go to a module external to the processor
	// These signals are described in the IO section
	input [7:0] in_data, // From IO Device
	output [7:0] out_data // To IO Device
);

wire [12:0] pc;
wire [7:0] immediate;
wire [7:0] r1;
wire [7:0] r2;
wire [7:0] r_data;
wire [7:0] v1;
wire [7:0] v2;
wire [7:0] result;
wire [7:0] dmem_data;
wire [15:0] instruction;

assign out_data = v1;
assign inst_out = instruction[15:12];

decode Dec(
    .inst_in( instruction[12:0] ), // Incoming instruction from the Imem (-opcode)

    .r1_out (r1), // The encoded register bits (going to the register file)
    .r2_out (r2),
	 
    .imm_out (immediate)   // The immediate (possibly ending up at the register file)
);

alu ALU(
    .v1_in(v1), // Incoming inputs from the register file
    .v2_in(v1), 
    .alu_op_code_in(alu_op_code_in), // Opcode of the operation to perform (derived from the ISA)

    .result_out(result) // Result of the given operation
);

mux4 reg_intput_mux ( 
	.input0(immediate), //[7:0]
	.input1(in_data), 
	.input2(dmem_data), 
	.input3(result),
   .sel(reg_sel_in), //[1:0]
	.out(r_data) //[7:0]
); 

reg_file regFile(
	.clk(clk), // clock
	.reset(reset), // reset
	
	.r1_in(r1), // register inputs - [1:0]
	.r2_in(r2),
	.r_data_in(r_data), // Data to be written on the next clock cycle
	.regfile_write_en_in(regfile_write_en_in), // Should we write this cycle?
	
	.v1_out(v1), //asychronous outputs
	.v2_out(v2)
);

i_mem_16_8192 iMem (
	a(pc), 	// address input [12:0]
	spo(instruction)   // data output [15:0]
);	

dmem dMemory(
	.reset(reset), // reset
	.clk(clk), // clock

	// Used to specify either a read or a write
	// request.
	// 1 -> read/write request
	// 0 -> no requests
	.dmem_read_write_req_in(dmem_read_write_req_in),
	.dmem_write_en_in(dmem_write_en_in), // Assert for writing (write enable)
	.addr(v2), // Address for data we'd like to retrieve [7:0]
	.din(v1), // Data input for writing [7:0]
	.dout(dmem_data), // Data output for reading [7:0]
	
	.refused // Don't worry about this output
);

programCounter PC(
	 .clk(clk), // clock
    .run_stall_reset_sel_in(run_stall_reset_sel_in), // control signal [1:0]
    .pc_out(pc)	// program counter output [15:0]
    );


endmodule
